﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NBehave.Narrator.Framework;
using RunAllTestsInSolutionTask;
using NUnit.Framework;
using System.IO;
using NCoverTasks;

namespace AcceptanceTesting
{
    [ActionSteps]
    public class Actions
    {
        private const string REDIRECTED_CONSOLE = "logfile.txt";
        private const string MSTEST = @"e:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\MSTest.exe";
        private const string NCOVER = @"e:\Program Files (x86)\NCover\NCover.Console.exe";

        private string _Solution;
        private RunAllTestsInSolution _Target;
        private NCoverAllTestInSolution _NCoverTarget;
        
        private static TextWriter _ConsoleOut;

        [Given("Solution $solutionName")]
        public void SolutionName(string solutionName)
        {
            _Target = new RunAllTestsInSolution();
            _NCoverTarget = new NCoverAllTestInSolution();
            _Solution = solutionName;
        }

        [When("Running in $mode Mode")]
        public void RunAllTests(string mode)
        {
            _Target.Configuration = mode;
            ExecuteTests();
        }

        [When("Running NCover in $mode Mode")]
        public void NCoverAllTests(string mode)
        {
            _NCoverTarget.Configuration = mode;
            ExecuteNCover();
        }

        [When("Excluding $projectName project")]
        public void Exclude(string projectName)
        {
            _Target.ExcludeProject = projectName;
        }
        
        [Then("$Num Tests Are Executed")]
        public void VerifyExecutedTestsCount(string Num)
        {
            int execuetedTestscount = GetNumberOfTestsFromLastRun();
            Assert.AreEqual(int.Parse(Num), execuetedTestscount);
        }

        #region Utilities Methods

        private void ExecuteTests()
        {
            try
            {
                _Target.SolutionFile = _Solution;
                _Target.MSTest = MSTEST;
                RedirectOutput();
                _Target.Execute();
            }
            finally
            {
                RestoreConsole();
            }
        }
        private void ExecuteNCover()
        {
            try
            {
                _NCoverTarget.NCoverConsole = NCOVER;
                _NCoverTarget.SolutionFile = _Solution;
                _NCoverTarget.MSTest = MSTEST;
                RedirectOutput();
                _NCoverTarget.Execute();
            }
            finally
            {
                RestoreConsole();
            }
        }

        private int GetNumberOfTestsFromLastRun()
        {
            var output = new StreamReader(REDIRECTED_CONSOLE);
            var data = output.ReadToEnd();
            output.Close();
            return GetTestsCount(data);
        }
        private int GetTestsCount(string data)
        {
            //Console.WriteLine(data);
            while (data.GetFirstWord() != "Total" && (!string.IsNullOrEmpty(data)))
                data = data.RemoveFirstWord();
            return int.Parse(data.RemoveFirstWord().RemoveFirstWord().GetFirstWord());
        }
        private static void RedirectOutput()
        {
            StreamWriter log_out;
            log_out = new StreamWriter(REDIRECTED_CONSOLE);
            _ConsoleOut = Console.Out;
            Console.SetOut(log_out);
        }
        private void RestoreConsole()
        {
            var currentconsole = Console.Out;
            Console.SetOut(_ConsoleOut);
            currentconsole.Close();

            ////Print output to screen
            //var output = new StreamReader(REDIRECTED_CONSOLE);
            //Console.WriteLine(output.ReadToEnd());
            //output.Close();
        }
        #endregion
    }
}
